home *** CD-ROM | disk | FTP | other *** search
- /*
- * lfsDesc.c --
- *
- * File descriptor management routines for LFS. The routine in
- * this module provide the interface for file descriptors I/O
- * and allocation for a LFS file system. The implementation uses
- * the file system block cache to cache groups of descriptors and
- * provide write buffering.
- *
- * Copyright 1989 Regents of the University of California
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- */
-
- #ifndef lint
- static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/lfs/lfsDesc.c,v 1.11 92/06/01 15:03:53 kupfer Exp $ SPRITE (Berkeley)";
- #endif /* not lint */
-
- #include <sprite.h>
- #include <lfs.h>
- #include <lfsInt.h>
- #include <lfsDesc.h>
- #include <lfsDescMap.h>
- #include <fs.h>
- #include <fsdm.h>
- #include <user/time.h>
-
-
- /*
- * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- * Start of routines exported to higher levels of the file system.
- * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- */
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Lfs_FileDescFetch() --
- *
- * Fetch the specified file descriptor from the file system and
- * store it in *fileDescPtr.
- *
- * Results:
- * An error if could not read the file descriptor from disk or is not
- * allocated.
- *
- * Side effects:
- * A block of descriptors may be read into the cache.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- Lfs_FileDescFetch(domainPtr, fileNumber, fileDescPtr)
- Fsdm_Domain *domainPtr; /* Domain to fetch file descriptor. */
- int fileNumber; /* Number of file descriptor to fetch.*/
- Fsdm_FileDescriptor *fileDescPtr; /* File descriptor structure to fetch.*/
- {
- Lfs *lfsPtr = LfsFromDomainPtr(domainPtr);
- LfsFileDescriptor *descPtr;
- Fscache_Block *blockPtr;
- ReturnStatus status;
- LfsDiskAddr diskAddr;
- int i, cacheFlags;
- Boolean found;
-
- LFS_STATS_INC(lfsPtr->stats.desc.fetches);
- status = LfsDescMapGetDiskAddr(lfsPtr, fileNumber, &diskAddr);
- if (status != SUCCESS) {
- return status;
- }
- cacheFlags = FSCACHE_DESC_BLOCK;
- if (LfsIsCleanerProcess(lfsPtr)) {
- cacheFlags |= FSCACHE_CANT_BLOCK;
- LFS_STATS_INC(lfsPtr->stats.desc.cleaningFetch);
- }
- /*
- * See if the value is in the descriptor block cache. If it is not
- * then read it in.
- */
- Fscache_FetchBlock(&lfsPtr->descCache.handle.cacheInfo,
- LfsDiskAddrToOffset(diskAddr), cacheFlags,
- &blockPtr, &found);
- if (!found) {
- LFS_STATS_INC(lfsPtr->stats.desc.fetchCacheMiss);
- if (LfsIsCleanerProcess(lfsPtr) &&
- (!lfsPtr->segCache.valid ||
- !LfsDiskAddrInRange(diskAddr, LfsBytesToBlocks(lfsPtr, 4096),
- lfsPtr->segCache.startDiskAddress,
- lfsPtr->segCache.endDiskAddress))) {
- LFS_STATS_INC(lfsPtr->stats.desc.cleaningFetchMiss);
- }
- status = LfsReadBytes(lfsPtr, diskAddr,
- lfsPtr->fileLayout.params.descPerBlock * sizeof(*descPtr),
- blockPtr->blockAddr);
- #ifdef ERROR_CHECK
- LfsCheckRead(lfsPtr, diskAddr,
- lfsPtr->fileLayout.params.descPerBlock * sizeof(*descPtr));
- #endif
- if (status != SUCCESS) {
- printf( "Could not read in file descriptor\n");
- Fscache_UnlockBlock(blockPtr, (time_t)0, -1, 0,
- FSCACHE_DELETE_BLOCK);
- return status;
- }
- }
- descPtr = (LfsFileDescriptor *) (blockPtr->blockAddr);
- for (i = 0; i < lfsPtr->fileLayout.params.descPerBlock; i++) {
- /*
- * The descriptor block is terminated by an inode
- * with a zero magic number.
- */
- if (descPtr->common.magic == 0) {
- break;
- }
- if (descPtr->common.magic != FSDM_FD_MAGIC) {
- LfsError(lfsPtr, FAILURE, "Bad descriptor magic number.\n");
- continue;
- }
- if (descPtr->fileNumber == fileNumber) {
- LFS_STATS_INC(lfsPtr->stats.desc.goodFetch);
- LFS_STATS_ADD(lfsPtr->stats.desc.fetchSearched,i);
- bcopy((char *) &(descPtr->common), (char *)fileDescPtr,
- sizeof(descPtr->common));
- status = LfsDescMapGetAccessTime(lfsPtr, fileNumber,
- &(fileDescPtr->accessTime));
- if (status != SUCCESS) {
- LfsError(lfsPtr, status, "Can't get access time.\n");
- }
- Fscache_UnlockBlock(blockPtr, (time_t)0, -1, FS_BLOCK_SIZE, 0);
- return SUCCESS;
- }
- descPtr++;
- }
- Fscache_UnlockBlock(blockPtr, (time_t)0, -1, 0, FSCACHE_DELETE_BLOCK);
- printf("Descriptor map foulup, can't find file %d at %d\n", fileNumber,
- LfsDiskAddrToOffset(diskAddr));
- LfsError(lfsPtr, FS_FILE_NOT_FOUND, "Descriptor map foulup.");
- return FS_FILE_NOT_FOUND;
-
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Lfs_FileDescStore() --
- * Store the given file descriptor back into the file system block
- * where it came from.
- *
- * Results:
- * An error if could not read the file descriptor from disk or is not
- * allocated.
- *
- * Side effects:
- * A block of descriptors may be read into the cache.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- Lfs_FileDescStore(domainPtr, handlePtr, fileNumber, fileDescPtr, forceOut)
- register Fsdm_Domain *domainPtr; /* Domain to store the file
- * descriptor into. */
- Fsio_FileIOHandle *handlePtr;
- int fileNumber; /* Number of file descriptor to
- store.*/
- Fsdm_FileDescriptor *fileDescPtr; /* File descriptor to store. */
- Boolean forceOut; /* Force the change to disk. */
- {
- Lfs *lfsPtr = LfsFromDomainPtr(domainPtr);
- ReturnStatus status = SUCCESS;
-
- LFS_STATS_INC(lfsPtr->stats.desc.stores);
- if (fileDescPtr->flags & FSDM_FD_FREE) {
- LFS_STATS_INC(lfsPtr->stats.desc.freeStores);
- return SUCCESS;
- }
- if (fileDescPtr->flags & FSDM_FD_ACCESSTIME_DIRTY) {
- status = LfsDescMapSetAccessTime(lfsPtr, fileNumber,
- fileDescPtr->accessTime);
- if (status != SUCCESS) {
- LfsError(lfsPtr, status, "Can't update descriptor map.\n");
- }
- fileDescPtr->flags &= ~FSDM_FD_ACCESSTIME_DIRTY;
- LFS_STATS_INC(lfsPtr->stats.desc.accessTimeUpdate);
- }
- if (fileDescPtr->flags & FSDM_FD_DIRTY) {
- LFS_STATS_INC(lfsPtr->stats.desc.dirtyList);
- Fscache_PutFileOnDirtyList(&handlePtr->cacheInfo,
- FSCACHE_FILE_DESC_DIRTY);
- }
- return status;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Lfs_FileTrunc --
- *
- * Shorten a file to length bytes. This updates the descriptor
- * and may free blocks and indirect blocks from the end of the file.
- *
- * Results:
- * Error if had problem with indirect blocks, otherwise SUCCESS.
- *
- * Side effects:
- * May modify the truncateVersion number.
- * Any allocated blocks after the given size are deleted.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- Lfs_FileTrunc(domainPtr, handlePtr, size, delete)
- Fsdm_Domain *domainPtr;
- Fsio_FileIOHandle *handlePtr; /* File to truncate. */
- int size; /* Size to truncate the file to. */
- Boolean delete; /* TRUE if Truncate for delete. */
- {
- Lfs *lfsPtr = LfsFromDomainPtr(domainPtr);
- Fsdm_FileDescriptor *descPtr;
- ReturnStatus status = SUCCESS;
- int newLastByte;
-
- if (size < 0) {
- return(GEN_INVALID_ARG);
- }
- LFS_STATS_INC(lfsPtr->stats.desc.truncs);
-
- descPtr = handlePtr->descPtr;
-
- newLastByte = size - 1;
- if (descPtr->lastByte <= newLastByte) {
- status = SUCCESS;
- goto exit;
- }
-
- /*
- * Pause the write back during the truncate to sync access to
- * file index.
- */
- Fscache_PreventWriteBacks(&handlePtr->cacheInfo);
- status = LfsFile_TruncIndex(lfsPtr, handlePtr, size);
- if (status == SUCCESS) {
- if (size == 0) {
- int newVersion;
- LFS_STATS_INC(lfsPtr->stats.desc.truncSizeZero);
- status = LfsDescMapIncVersion(lfsPtr,
- handlePtr->hdr.fileID.minor, &newVersion);
- }
- descPtr->lastByte = newLastByte;
- descPtr->descModifyTime = Fsutil_TimeInSeconds();
- if (delete) {
- /*
- * XXX - need sync here.
- */
- descPtr->flags &= ~FSDM_FD_DIRTY;
- } else {
- descPtr->flags |= FSDM_FD_SIZE_DIRTY;
- }
- }
- Fscache_AllowWriteBacks(&handlePtr->cacheInfo);
- exit:
- if (delete) {
- LFS_STATS_INC(lfsPtr->stats.desc.delete);
- /*
- * XXX - need sync here.
- */
- descPtr->flags &= ~FSDM_FD_DIRTY;
- status = Fscache_RemoveFileFromDirtyList(&handlePtr->cacheInfo);
- } else {
- if (descPtr->flags & FSDM_FD_DIRTY) {
- status = Fscache_PutFileOnDirtyList(&handlePtr->cacheInfo,
- FSCACHE_FILE_DESC_DIRTY);
- }
- }
- return status;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Lfs_FileDescInit() --
- *
- * Initialize a new file descriptor.
- *
- * Results:
- * SUCCESS
- *
- * Side effects:
- * The file decriptor is initialized.
- *
- *----------------------------------------------------------------------
- */
- /*ARGSUSED*/
- ReturnStatus
- Lfs_FileDescInit(domainPtr, fileNumber, type, permissions, uid, gid, fileDescPtr)
- Fsdm_Domain *domainPtr; /* Domain of the file */
- int fileNumber; /* Number of file descriptor */
- int type; /* Type of the file */
- int permissions; /* Permission bits for the file */
- int uid; /* Owner ID for the file */
- int gid; /* Group ID for the file */
- Fsdm_FileDescriptor *fileDescPtr; /* File descriptor structure to
- initialize. */
- {
- register int index;
- LFS_STATS_INC((LfsFromDomainPtr(domainPtr))->stats.desc.inits);
-
- fileDescPtr->magic = FSDM_FD_MAGIC;
- fileDescPtr->flags = FSDM_FD_ALLOC|FSDM_FD_DIRTY;
- fileDescPtr->fileType = type;
- fileDescPtr->permissions = permissions;
- fileDescPtr->uid = uid;
- fileDescPtr->gid = gid;
- fileDescPtr->lastByte = -1;
- fileDescPtr->lastByteXtra = 0;
- fileDescPtr->firstByte = -1;
- fileDescPtr->userType = FS_USER_TYPE_UNDEFINED;
- fileDescPtr->numLinks = 1;
-
- /*
- * Clear out device info. It is set up properly by the make-device routine.
- */
- fileDescPtr->devServerID = -1;
- fileDescPtr->devType = -1;
- fileDescPtr->devUnit = -1;
-
- /*
- * Set the time stamps. These times should come from the client.
- */
- fileDescPtr->createTime = Fsutil_TimeInSeconds();
- fileDescPtr->accessTime = fileDescPtr->createTime;
- fileDescPtr->descModifyTime = fileDescPtr->createTime;
- fileDescPtr->dataModifyTime = fileDescPtr->createTime;
-
- for (index = 0; index < FSDM_NUM_DIRECT_BLOCKS ; index++) {
- fileDescPtr->direct[index] = FSDM_NIL_INDEX;
- }
- for (index = 0; index < FSDM_NUM_INDIRECT_BLOCKS ; index++) {
- fileDescPtr->indirect[index] = FSDM_NIL_INDEX;
- }
- fileDescPtr->numKbytes = 0;
- /*
- * Give this new file a new version number. The increment is by 2 to
- * ensure that a client invalidates any cache blocks associated with
- * the previous incarnation of the file. Remember that when a client
- * opens for writing a version number 1 greater means that its old
- * cache blocks are still ok, and also remember that clients with
- * clean blocks are not told when a file is deleted.
- */
- fileDescPtr->version = LfsGetCurrentTimestamp(LfsFromDomainPtr(domainPtr));
- return(SUCCESS);
- }
-
- /*
- * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- * End of routines exported to higher levels of the file system.
- * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- *
- * Start of LFS private routines.
- */
-
- /*
- *----------------------------------------------------------------------
- *
- * LfsDescCacheInit --
- *
- * Initialize the descriptor cache for a file system.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- void
- LfsDescCacheInit(lfsPtr)
- Lfs *lfsPtr;
- {
- Fscache_Attributes attr;
- /*
- * Initialize the file handle used to cache descriptor blocks.
- */
-
- bzero((char *)(&lfsPtr->descCache.handle),sizeof(lfsPtr->descCache.handle));
- lfsPtr->descCache.handle.hdr.fileID.serverID = rpc_SpriteID;
- lfsPtr->descCache.handle.hdr.fileID.major = lfsPtr->domainPtr->domainNumber;
- lfsPtr->descCache.handle.hdr.fileID.minor = 0;
- lfsPtr->descCache.handle.hdr.fileID.type = FSIO_LCL_FILE_STREAM;
- lfsPtr->descCache.handle.descPtr = (Fsdm_FileDescriptor *)NIL;
-
-
- bzero((Address)&attr, sizeof(attr));
- attr.lastByte = 0x7fffffff;
- Fscache_FileInfoInit(&lfsPtr->descCache.handle.cacheInfo,
- (Fs_HandleHeader *) &lfsPtr->descCache.handle,
- 0, TRUE, &attr, lfsPtr->domainPtr->backendPtr);
-
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * LfsDescCacheDestory --
- *
- * Destory the descriptor cache for a file system.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- void
- LfsDescCacheDestory(lfsPtr)
- Lfs *lfsPtr;
- {
-
- Fscache_FileInvalidate(&lfsPtr->descCache.handle.cacheInfo, 0,
- FSCACHE_LAST_BLOCK);
-
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * LfsDescCacheBlockInit --
- *
- * Initialize a block into the descriptor cache for a file system.
- *
- * Results:
- * NIL if the block couldn't be initialized. A clientData otherwise.
- *
- * Side effects:
- * Cache block is fetched and held.
- *
- *----------------------------------------------------------------------
- */
-
- ClientData
- LfsDescCacheBlockInit(lfsPtr, diskBlockAddr, cantBlock, blockStartPtr)
- Lfs *lfsPtr; /* File system. */
- LfsDiskAddr diskBlockAddr; /* Descriptor cache block address. */
- Boolean cantBlock; /* TRUE if process can`t block. */
- char **blockStartPtr; /* OUT: pointer to lock's contents. */
- {
- Fscache_Block *blockPtr;
- int blockNum;
- Boolean found;
-
- blockNum = LfsDiskAddrToOffset(diskBlockAddr);
- Fscache_FetchBlock(&lfsPtr->descCache.handle.cacheInfo,
- blockNum, (FSCACHE_DESC_BLOCK|FSCACHE_CANT_BLOCK| (cantBlock ? FSCACHE_DONT_BLOCK:0)),
- &blockPtr, &found);
- if (blockPtr == (Fscache_Block *) NIL) {
- return (ClientData) blockPtr;
- }
- if (!found) {
- if ((*blockStartPtr) != (char *) NIL) {
- bcopy(*blockStartPtr, blockPtr->blockAddr,
- lfsPtr->fileLayout.params.descPerBlock *
- LFS_FILE_DESC_SIZE);
- } else {
- bzero(blockPtr->blockAddr, lfsPtr->fileLayout.params.descPerBlock *
- LFS_FILE_DESC_SIZE);
- }
- Fscache_IODone(blockPtr);
- } else {
- #ifdef ERROR_CHECK
- if (((*blockStartPtr) != (char *) NIL) &&
- (bcmp(*blockStartPtr, blockPtr->blockAddr,
- lfsPtr->fileLayout.params.descPerBlock * LFS_FILE_DESC_SIZE)
- != 0)) {
- panic("LfsDescCacheBlockInit found wrong block\n");
- }
- #endif
- }
- if (*blockStartPtr == (char *) NIL) {
- *blockStartPtr = blockPtr->blockAddr;
- }
- return (ClientData) blockPtr;
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * LfsDescCacheBlockRelease --
- *
- * Release a desc cache block return by LfsDescCacheBlockInit.
- *
- * Results:
- * void
- *
- * Side effects:
- *
- *----------------------------------------------------------------------
- */
-
- void
- LfsDescCacheBlockRelease(lfsPtr, clientData, deleteBlock)
- Lfs *lfsPtr;
- ClientData clientData;
- Boolean deleteBlock; /* TRUE if block should be deleted. */
- {
- Fscache_Block *blockPtr = (Fscache_Block *) clientData;
- Fscache_UnlockBlock(blockPtr,(time_t)0, -1, FS_BLOCK_SIZE,
- deleteBlock ? FSCACHE_DELETE_BLOCK : 0);
- }
-
-